package com.boarsoft.boar.config.apollo;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.boarsoft.common.util.InetUtil;
import com.boarsoft.common.util.JsonUtil;
import com.boarsoft.common.util.StreamUtil;

/**
 * 
 * @author Mac_J
 *
 */
public class ApolloPuller {
	private static final Logger log = LoggerFactory.getLogger(ApolloPuller.class);

	/**
	 * 不带缓存的配置更新接口<br>
	 * 此的配置格式如下：<br>
	 * http://{config_server_url}/configs/{appId}/{clusterName}/<br>
	 * 实际发起时需要实上以下部份：<br>
	 * {namespaceName}?releaseKey={releaseKey}&ip={clienIp}<br>
	 * config_server_url：Apollo配置服务的地址<br>
	 * appId：应用的appId<br>
	 * clusterName：集群名<br>
	 * namespaceName：如果没有新建过Namespace的话，传入application即可。
	 * 如果创建了Namespace，并且需要使用该Namespace的配置，则传入对应的Namespace名字。<br>
	 * 对于properties类型的namespace，只需要传入namespace的名字<br>
	 * 对于其它类型的namespace，需要传入namespace的名字加上后缀名，如datasources.json<br>
	 * releaseKey:
	 * 将上一次返回对象中的releaseKey传入即可，用来给服务端比较版本，如果版本比下来没有变化，则服务端直接返回304以节省流量和运算
	 */
	protected String url;
	protected String appId;
	protected String secret;
	protected String encIn = "UTF-8";
	protected List<Notification> notifactions;

	/** 上一次的releaseKey */
	protected String releaseKey;
	protected String ip = InetUtil.getIp();

	public String pull(String namespaceName) throws UnsupportedEncodingException {
		StringBuilder sb = new StringBuilder();
		sb.append(url).append(namespaceName).append("?releaseKey=")//
				.append(releaseKey).append("&ip=").append(ip);
		String s = sb.toString();
		log.debug("Pulling config file from apollo server with {}", s);
		PrintWriter out = null;
		BufferedReader br = null;
		HttpURLConnection conn = null;
		try {
			conn = (HttpURLConnection) new URL(s).openConnection();
			conn.setConnectTimeout(3000);// 连接3秒超时
			conn.setReadTimeout(3000);// 读也为3秒超时
			conn.setRequestProperty("User-Agent", "Mozilla/5.0");
			conn.setRequestProperty("Content-Type", encIn);
			conn.setRequestMethod("GET");
			// HTTP请求头
			Map<String, String> headers = Signature.buildHttpHeaders(url, appId, secret);
			if (headers != null && headers.size() > 0) {
				for (String h : headers.keySet()) {
					conn.setRequestProperty(h, headers.get(h));
				}
			}
			// 不需要报文体
			// out = new PrintWriter(conn.getOutputStream());
			// out.print(body);
			// out.flush();
			br = new BufferedReader(new InputStreamReader(conn.getInputStream(), encIn));
			String line = null;
			while ((line = br.readLine()) != null) {
				// sb.append(line).append(FileUtil.LINE_SEPARATOR);
				sb.append(line).append("\n");
			}
			switch (conn.getResponseCode()) {
			case 200: // 配置有变化，更新配置
				this.update(sb.toString());
				break;
			case 304: // 配置无变化
				break;
			}
		} catch (UnsupportedEncodingException e) {

		} catch (IOException e) {

		} finally {
			StreamUtil.close(br);
			StreamUtil.close(out);
			if (conn != null) {
				conn.disconnect();
			}
		}
		return sb.toString();
	}

	public void update(String json) {
		NamespaceMeta m = JsonUtil.parseObject(json, NamespaceMeta.class);
		// TODO
	}

	public String getAppId() {
		return appId;
	}

	public void setAppId(String appId) {
		this.appId = appId;
	}

	public String getSecret() {
		return secret;
	}

	public void setSecret(String secret) {
		this.secret = secret;
	}

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public String getEncIn() {
		return encIn;
	}

	public void setEncIn(String encIn) {
		this.encIn = encIn;
	}
}